﻿using LightCAD.MathLib.Csg;
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Numerics;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace LightCAD.MathLib
{

    public partial class GeoUtils
    {
        public static bool IsPointInPolygon(Vector2 point, Vector2[] polygon)
        {
            int polygonLength = polygon.Length, i = 0;
            bool inside = false;
            // x, y for tested point.
            double pointX = point.X, pointY = point.Y;
            // start / end point for the current polygon segment.
            double startX, startY, endX, endY;
            Vector2 endPoint = polygon[polygonLength - 1];
            endX = endPoint.X;
            endY = endPoint.Y;
            while (i < polygonLength)
            {
                startX = endX; startY = endY;
                endPoint = polygon[i++];
                endX = endPoint.X; endY = endPoint.Y;
                //
                inside ^= (endY > pointY ^ startY > pointY) /* ? pointY inside [startY;endY] segment ? */
                          && /* if so, test if it is under the segment */
                          ((pointX - endX) < (pointY - endY) * (startX - endX) / (startY - endY));
            }
            return inside;
        }

        public static bool IsConvexPolygon(Vector2[] points)
        {
            int vertexCount = points.Length;

            if (vertexCount < 3) // 多边形至少需要3个顶点才能判断凸性
                return false;

            bool isClockwise = false;
            bool isCounterClockwise = false;

            for (int i = 0; i < vertexCount; i++)
            {
                Vector2 currentVertex = points[i];
                Vector2 nextVertex = points[(i + 1) % vertexCount];
                Vector2 previousVertex = points[(i - 1 + vertexCount) % vertexCount];

                Vector2 currentEdge = nextVertex - currentVertex;
                Vector2 previousEdge = currentVertex - previousVertex;

                double crossProduct = Vector2.Cross(previousEdge, currentEdge);

                if (crossProduct < 0)
                    isCounterClockwise = true;
                else if (crossProduct > 0)
                    isClockwise = true;

                if (isClockwise && isCounterClockwise)
                    return false; // 多边形同时存在顺时针和逆时针方向，不是凸多边形
            }
            return true;
        }

        public static double PointDistanceToLine(Vector2 point, Vector2 start, Vector2 end)
        {
            // 计算直线上的向量V
            Vector2 v = end - start;
            // 计算从P1到P的向量W
            Vector2 w = point - start;

            // 计算投影向量Proj
            double dotProduct = Vector2.Dot(w, v);
            var proj = (dotProduct / v.LengthSq()) * v;

            // 计算距离d
            Vector2 diff = w - proj;
            return diff.Length();
        }
        public static Vector2 ArcCrossLine(Arc2d arc2d, Line2d line2D)  //圆弧与直线的交点 重载调用
        {
            ////计算直线的方向向量
            //double dx = line2D.End.X - line2D.Start.X;
            //double dy = line2D.End.Y - line2D.Start.Y;
            ////计算直线的参数化方程
            //double a = dx * dx + dy * dy;
            //double b = 2 * (dx * (line2D.Start.X - this.Center.X) + dy * (line2D.Start.Y - this.Center.Y));
            //double c = Math.Pow((line2D.Start.X - this.Center.X), 2) + Math.Pow((line2D.Start.Y - this.Center.Y), 2) - Math.Pow(this.Radius, 2);
            ////计算判别式
            //double discriminant = b * b - 4 * a * c;
            //Vector2 point = new Vector2();
            //if (discriminant >= 0)
            //{
            //    if (Math.Abs(discriminant) < 1e-6)   //直线与圆只有一个切点
            //    {
            //        double t = -b / (2 * a);
            //        point = new Vector2(line2D.Start.X + t * dx, line2D.Start.Y + t * dy);
            //    }
            //    else                               //直线与圆有两个交点
            //    {
            //        double t1 = (-b + (float)Math.Sqrt(discriminant)) / (2 * a);
            //        double t2 = (-b - (float)Math.Sqrt(discriminant)) / (2 * a);
            //        Vector2 point1 = new Vector2(line2D.Start.X + t1 * dx, line2D.Start.Y + t1 * dy);
            //        Vector2 point2 = new Vector2(line2D.Start.X + t2 * dx, line2D.Start.Y + t2 * dy);
            //        if (Vector2.Distance(point1, line2D.Start) < Vector2.Distance(point2, line2D.Start))
            //        {
            //            point = point1;
            //        }
            //        else
            //        {
            //            point = point2;
            //        }
            //    }
            //}
            Vector2 point = Circle2d.GetCrossCircleLine(new Line2d(line2D.Start, line2D.End), arc2d.Center, arc2d.Radius);
            return point;
        }
        public static Vector2 FindFoot(Vector2 pntSart, Vector2 pntEnd, Vector2 pA)
        {
            Vector2 pFoot = new Vector2();
            double k = 0;
            if (pntSart.X == pntEnd.X)
            {
                pFoot.X = pntSart.X;
                pFoot.Y = pA.Y;
                return pFoot;
            }
            k = (pntEnd.Y - pntSart.Y) * 1.0 / (pntEnd.X - pntSart.X);
            double A = k;
            double B = -1.0;
            double C = pntSart.Y - k * pntSart.X;

            pFoot.X = (B * B * pA.X - A * B * pA.Y - A * C) / (A * A + B * B);
            pFoot.Y = (A * A * pA.Y - A * B * pA.X - B * C) / (A * A + B * B);
            return pFoot;
        }

        public static Vector2 GetCrossVector(Line2d first, Line2d second)  //线与线的交点
        {

            Vector2 cp = new Vector2();
            // 定义第一条线段的起点和终点坐标
            double x1 = first.Start.X;
            double y1 = first.Start.Y;
            double x2 = first.End.X;
            double y2 = first.End.Y;

            // 定义第二条线段的起点和终点坐标
            double x3 = second.Start.X;
            double y3 = second.Start.Y;
            double x4 = second.End.X;
            double y4 = second.End.Y;
            // 计算两条线段的斜率
            double slope1 = (y2 - y1) / (x2 - x1);
            double slope2 = (y4 - y3) / (x4 - x3);
            //判断两条线是否平行
            if (Math.Abs(slope1 - slope2) < 0.0001)
            {
                return null;
            }
            //判断两条线的垂直的可能性
            //如果第一条线垂直
            if (x1 == x2 && x3 != x4)
            {
                //y=kx+b
                double b = y4 - slope2 * x4;
                double X = x1;
                double Y = slope2 * x1 + b;
                cp.X = X;
                cp.Y = Y;
            }
            if (x1 != x2 && x3 == x4)
            {
                double b = y2 - slope1 * x2;
                double X = x3;
                double Y = slope1 * x3 + b;
                cp.X = X;
                cp.Y = Y;
            }
            else
            {
                double X = ((x3 * y4 - x4 * y3) * (x2 - x1) - (x1 * y2 - x2 * y1) * (x4 - x3)) /
                                  ((y1 - y2) * (x4 - x3) - (y3 - y4) * (x2 - x1));
                double Y = ((y3 * x4 - y4 * x3) * (y2 - y1) - (y1 * x2 - y2 * x1) * (y4 - y3)) /
                                 ((x1 - x2) * (y4 - y3) - (x3 - x4) * (y2 - y1));
                cp.X = X;
                cp.Y = Y;
            }
            return cp;

        }
        public static List<Vector2> GetCrossCircleLine(Vector2 sp, Vector2 ep, Vector2 Center, double Radius)  //圆与直线的交点 重载调用
        {
            //计算直线的方向向量
            double dx = ep.X - sp.X;
            double dy = ep.Y - sp.Y;
            //计算直线的参数化方程
            double a = dx * dx + dy * dy;
            double b = 2 * (dx * (sp.X - Center.X) + dy * (sp.Y - Center.Y));
            double c = Math.Pow((sp.X - Center.X), 2) + Math.Pow((sp.Y - Center.Y), 2) - Math.Pow(Radius, 2);
            //计算判别式
            double discriminant = b * b - 4 * a * c;
            List<Vector2> points = new List<Vector2>();
            Vector2 point = new Vector2();
            if (discriminant >= 0)
            {
                if (Math.Abs(discriminant) < 1e-6)   //直线与圆只有一个切点
                {
                    double t = -b / (2 * a);
                    point = new Vector2(sp.X + t * dx, sp.Y + t * dy);
                    points.Add(point);
                }
                else                               //直线与圆有两个交点
                {
                    double t1 = (-b + (float)Math.Sqrt(discriminant)) / (2 * a);
                    double t2 = (-b - (float)Math.Sqrt(discriminant)) / (2 * a);
                    Vector2 point1 = new Vector2(sp.X + t1 * dx, sp.Y + t1 * dy);
                    Vector2 point2 = new Vector2(sp.X + t2 * dx, sp.Y + t2 * dy);
                    points.Add(point1);
                    points.Add(point2);
                    //if (Vector2.Distance(point1, sp) < Vector2.Distance(point2, sp))
                    //{
                    //    point = point1;
                    //}
                    //else
                    //{
                    //    point = point2;
                    //}
                }
            }
            if (points == null)
            {
                return null;
            }
            return points;
        }
        public static List<Vector2> GetCrossLineArc(Vector2 sp, Vector2 ep, Vector2 Center, double Radius)  //圆弧与直线的交点 重载调用
        {
            List<Vector2> points = new List<Vector2>();
            //计算直线的方向向量
            double dx = ep.X - sp.X;
            double dy = ep.Y - sp.Y;
            //计算直线的参数化方程
            double a = dx * dx + dy * dy;
            double b = 2 * (dx * (sp.X - Center.X) + dy * (sp.Y - Center.Y));
            double c = Math.Pow((sp.X - Center.X), 2) + Math.Pow((sp.Y - Center.Y), 2) - Math.Pow(Radius, 2);
            //计算判别式
            double discriminant = b * b - 4 * a * c;
            Vector2 point1 = new Vector2();
            Vector2 point2 = new Vector2();
            if (discriminant >= 0)
            {
                if (Math.Abs(discriminant) < 1e-6)   //直线与圆只有一个切点
                {
                    double t = -b / (2 * a);
                    point1 = new Vector2(sp.X + t * dx, sp.Y + t * dy);
                    points.Add(point1);
                }
                else                               //直线与圆有两个交点
                {
                    double t1 = (-b + (float)Math.Sqrt(discriminant)) / (2 * a);
                    double t2 = (-b - (float)Math.Sqrt(discriminant)) / (2 * a);
                    point1 = new Vector2(sp.X + t1 * dx, sp.Y + t1 * dy);
                    point2 = new Vector2(sp.X + t2 * dx, sp.Y + t2 * dy);
                    points.Add(point1);
                    points.Add(point2);
                    //if (Vector2.Distance(point1, sp) < Vector2.Distance(point2, sp))
                    //{
                    //    points.add
                    //    point = point1;
                    //}
                    //else
                    //{
                    //    point = point2;
                    //}

                }
            }

            return points;
        }

        public static List<Vector2> ArcCrossArc(Arc2d arc2d1, Arc2d arc2d2)//圆弧与圆弧的交点(其实核心是圆与圆的交点)
        {
            List<Vector2> points = new List<Vector2>();
            double dx = arc2d2.Center.X - arc2d1.Center.X;
            double dy = arc2d2.Center.Y - arc2d1.Center.Y;
            double d = Math.Sqrt(dx * dx + dy * dy);
            // 判断两个圆是否相离或内含
            if (d > arc2d1.Radius + arc2d2.Radius || d < Math.Abs(arc2d1.Radius - arc2d2.Radius))
            {
                return null; // 无交点
            }
            else if (d == 0 && arc2d1.Radius == arc2d2.Radius)
            {
                return null; // 无限多个交点
            }
            else if (d == arc2d1.Radius + arc2d2.Radius)  //有一个交点
            {
                Vector2 point1 = new Vector2();
                point1.X = arc2d1.Center.X + (arc2d2.Center.X - arc2d1.Center.X) * arc2d1.Radius / (arc2d1.Radius + arc2d2.Radius);
                point1.Y = arc2d1.Center.Y + (arc2d2.Center.Y - arc2d1.Center.Y) * arc2d1.Radius / (arc2d1.Radius + arc2d2.Radius);
                points.Add(point1);
                return points;
            }
            else
            {
                double a = (arc2d1.Radius * arc2d1.Radius - arc2d2.Radius * arc2d2.Radius + d * d) / (2 * d);
                double h = Math.Sqrt(arc2d1.Radius * arc2d1.Radius - a * a);
                double x2 = arc2d1.Center.X + a * dx / d;
                double y2 = arc2d1.Center.Y + a * dy / d;
                double intersectionX1 = x2 + h * dy / d;
                double intersectionY1 = y2 - h * dx / d;
                double intersectionX2 = x2 - h * dy / d;
                double intersectionY2 = y2 + h * dx / d;
                Vector2 point1 = new Vector2(intersectionX1, intersectionY1);
                Vector2 point2 = new Vector2(intersectionX2, intersectionY2);
                points.Add(point1);
                points.Add(point2);
                return points;
            }
        }
        public static List<Vector2> CircleCrossArc(Circle2d circle1, Arc2d arc2D)//圆与圆弧的交点
        {
            List<Vector2> points = new List<Vector2>();
            double dx = arc2D.Center.X - circle1.Center.X;
            double dy = arc2D.Center.Y - circle1.Center.Y;
            double d = Math.Sqrt(dx * dx + dy * dy);
            // 判断两个圆是否相离或内含
            if (d > circle1.Radius + arc2D.Radius || d < Math.Abs(circle1.Radius - arc2D.Radius))
            {
                return null; // 无交点
            }
            else if (d == 0 && circle1.Radius == arc2D.Radius)
            {
                return null; // 无限多个交点
            }
            else if (d == circle1.Radius + arc2D.Radius)  //有一个交点
            {
                Vector2 point1 = new Vector2();
                point1.X = circle1.Center.X + (arc2D.Center.X - circle1.Center.X) * circle1.Radius / (circle1.Radius + arc2D.Radius);
                point1.Y = circle1.Center.Y + (arc2D.Center.Y - circle1.Center.Y) * circle1.Radius / (circle1.Radius + arc2D.Radius);
                points.Add(point1);
                return points;
            }
            else
            {
                double a = (circle1.Radius * circle1.Radius - arc2D.Radius * arc2D.Radius + d * d) / (2 * d);
                double h = Math.Sqrt(circle1.Radius * circle1.Radius - a * a);
                double x2 = circle1.Center.X + a * dx / d;
                double y2 = circle1.Center.Y + a * dy / d;
                double intersectionX1 = x2 + h * dy / d;
                double intersectionY1 = y2 - h * dx / d;
                double intersectionX2 = x2 - h * dy / d;
                double intersectionY2 = y2 + h * dx / d;
                Vector2 point1 = new Vector2(intersectionX1, intersectionY1);
                Vector2 point2 = new Vector2(intersectionX2, intersectionY2);
                points.Add(point1);
                points.Add(point2);
                return points;
            }
        }
        public static List<Vector2> CircleCrossCircle(Circle2d circle1, Circle2d circle2)//圆与圆弧的交点
        {
            List<Vector2> points = new List<Vector2>();
            double dx = circle2.Center.X - circle1.Center.X;
            double dy = circle2.Center.Y - circle1.Center.Y;
            double d = Math.Sqrt(dx * dx + dy * dy);
            // 判断两个圆是否相离或内含
            if (d > circle1.Radius + circle2.Radius || d < Math.Abs(circle1.Radius - circle2.Radius))
            {
                return null; // 无交点
            }
            else if (d == 0 && circle1.Radius == circle2.Radius)
            {
                return null; // 无限多个交点
            }
            else if (d == circle1.Radius + circle2.Radius)  //有一个交点
            {
                Vector2 point1 = new Vector2();
                point1.X = circle1.Center.X + (circle2.Center.X - circle1.Center.X) * circle1.Radius / (circle1.Radius + circle2.Radius);
                point1.Y = circle1.Center.Y + (circle2.Center.Y - circle1.Center.Y) * circle1.Radius / (circle1.Radius + circle2.Radius);
                points.Add(point1);
                return points;
            }
            else
            {
                double a = (circle1.Radius * circle1.Radius - circle2.Radius * circle2.Radius + d * d) / (2 * d);
                double h = Math.Sqrt(circle1.Radius * circle1.Radius - a * a);
                double x2 = circle1.Center.X + a * dx / d;
                double y2 = circle1.Center.Y + a * dy / d;
                double intersectionX1 = x2 + h * dy / d;
                double intersectionY1 = y2 - h * dx / d;
                double intersectionX2 = x2 - h * dy / d;
                double intersectionY2 = y2 + h * dx / d;
                Vector2 point1 = new Vector2(intersectionX1, intersectionY1);
                Vector2 point2 = new Vector2(intersectionX2, intersectionY2);
                points.Add(point1);
                points.Add(point2);
                return points;
            }
        }

        /// <summary>
        /// 椭圆与线的交点
        /// </summary>
        /// <param name="c">椭圆圆心</param>
        /// <param name="rx">椭圆x轴半径</param>
        /// <param name="ry">椭圆y轴半径</param>
        /// <param name="a1">线的起点坐标</param>
        /// <param name="a2"> 线的终点坐标</param>
        /// <returns></returns>
        public static List<Vector2> CrossEllipseLine(double Rotation, Vector2 c1, double rx, double ry, Vector2 a1, Vector2 a2)
        {
            //将圆心、直线起点、终点围绕椭圆圆心进行旋转
            Matrix3 matrix3 = Matrix3.RotateInRadian(0 - Rotation, c1);
            Vector2 c = matrix3.MultiplyPoint(c1);
            a1 = matrix3.MultiplyPoint(a1);
            a2= matrix3.MultiplyPoint(a2);

            List<Vector2> points = new List<Vector2>();
            List<Vector2> rps = new List<Vector2>();
            Vector2 orign = new Vector2(a1.X, a1.Y);
            Vector2 dir = new Vector2(a2.X - a1.X, a2.Y - a1.Y);
            Vector2 center = new Vector2(c.X, c.Y);
            Vector2 diff = new Vector2(orign.X - center.X, orign.Y - center.Y);

            Vector2 mDir = new Vector2(dir.X / (rx * rx), dir.Y / (ry * ry));
            Vector2 mDiff = new Vector2(diff.X / (rx * rx), diff.Y / (ry * ry));

            double a = dir.X * mDir.X + dir.Y * mDir.Y;
            double b = dir.X * mDiff.X + dir.Y * mDiff.Y;
            double cc = diff.X * mDiff.X + diff.Y * mDiff.Y - 1.0;
            double d = b * b - a * cc;
            if (d < 0)
            {
                return null;
            }
            else if (d > 0)
            {
                double root = Math.Sqrt(d);
                double t_a = (-b - root) / a;
                double t_b = (-b + root) / a;

                Vector2 point = new Vector2(a1.X * (1.0 - t_a) + a2.X * t_a, a1.Y * (1.0 - t_a) + a2.Y * t_a);
                points.Add(point);

                Vector2 point2 = new Vector2(a1.X * (1.0 - t_b) + a2.X * t_b, a1.Y * (1.0 - t_b) + a2.Y * t_b);
                points.Add(point2);

            }
            //将计算出来的交点最后旋转回去
            if (points != null)
            {
                Matrix3 sctow = Matrix3.RotateInRadian(Rotation, c1);
                foreach (var item in points)
                {
                    rps.Add(sctow.MultiplyPoint(item));
                }
                return rps;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 椭圆与椭圆求交点
        /// </summary>
        /// <param name="firstEllipse">第一个椭圆</param>
        /// <param name="secondEllipse">第二个椭圆</param>
        /// <returns></returns>
        public static List<Vector2> GetIntersectionPoints(Ellipse2d firstEllipse, Ellipse2d secondEllipse)
        {
            double a = firstEllipse.RadiusX;
            double b = firstEllipse.RadiusY;
            double c= secondEllipse.RadiusX;
            double d= secondEllipse.RadiusY;
            double phi = firstEllipse.Rotation;
            double phi0=secondEllipse.Rotation-phi;
            Vector2 position1 = new Vector2(secondEllipse.Center.X - firstEllipse.Center.X, secondEllipse.Center.Y - firstEllipse.Center.Y);
            Vector2 p0 =position1.RotateAround(new Vector2(0, 0), -phi);
  
           

            double A = p0.X / a;
            double B = c * Math.Cos(phi0) / a;
            double C=-d*Math.Sin(phi0)/a;
            double D = p0.Y / b;
            double E = c * Math.Sin(phi0) / b;
            double F = d*Math.Cos(phi0)/b;

            double G = B * B + E * E - C * C - F * F;
            double H = 2 * (A * B + D * E);
            double I= 2 * (B * C + E * F);
            double J= 2 * (A * C + D * F);
            double K= A * A + D * D + C * C + F * F - 1;

            List<double> roots = new List<double>();

            double L= G * G + I * I;
            if (Math.Abs(L) <1e-7)
            {
                double b1 = 2 * K * H;
                double a1 = H * H + J * J;
                double c1 = K * K - J * J;
                roots = EllipseAndEllipse.SolveQuadraticEquation(a1, b1, c1);
            }
            else
            {
                double M = 2 * (G * H + I * J);
                double N = H * H + 2 * G * K + J * J - I * I;
                double O = 2 * (K * H - I * J);
                double P = K * K - J * J;

                double iL = 1 / L;

                roots = EllipseAndEllipse.SolveQuarticEquation(M * iL, N * iL, O * iL, P * iL);
            }

            List<Vector2> points = new List<Vector2>();
            for(var i = 0; i < roots.Count; i++)
            {
                double x = roots[i] ;
                if (Math.Sqrt(I * x + J) < 1e-7)
                {
                    double y = Math.Sqrt(1 - x * x);

                    points.Add(new Vector2(x, y));
                    if(Math.Sqrt(y) >= 1e-7)
                    {
                        points.Add(new Vector2(x, -y));
                    }
                }
                else
                {
                    double y = -(G * x * x + H * x + K) / (I * x + J);
                    
                    if (Math.Abs(y) < 1e-2)
                    {
                        y = Math.Sqrt(1 - x * x);
                        points.Add(new Vector2(x, y));
                        points.Add(new Vector2(x, -y));
                    }
                    else
                    {
                        points.Add(new Vector2(x, y));
                    }
                }
            }

            for(var i = 0; i < roots.Count; i++)
            {
                points[i] = new Vector2((A + B * points[i].X + C * points[i].Y) * a, (D + E * points[i].X + F * points[i].Y) * b);
            }
            for (var i = 0; i < roots.Count; i++)
            {
                points[i]=points[i].RotateAround(new Vector2(0, 0), phi);
                points[i] = new Vector2(points[i].X+ firstEllipse.Center.X, points[i].Y + firstEllipse.Center.Y);
            }
                return points;
        }

   

        public static bool IsCircleInPolygon(Vector2 center, double radius, Vector2[] polygon)
        {

            for (int i = 0; i < polygon.Length; i++)
            {
                int j = (i + 1) % polygon.Length;

                if (CircleIntersectLine(center, radius, polygon[i], polygon[j]))
                    return false;
            }
            return IsPointInPolygon(center, polygon);

        }

        public static bool CircleIntersectLine(Vector2 center, double radius, Vector2 p1, Vector2 p2)
        {
            Vector2 v = p2 - p1;
            Vector2 w = center - p1;

            double t = Vector2.Dot(w, v) / Vector2.Dot(v, v);

            if (t < 0 || t > 1)
                return false;

            Vector2 projection = p1 + t * v;
            double distanceSquared = (center - projection).LengthSq();

            return distanceSquared <= radius * radius;
        }

        public static bool IsPolygonIntersectCircle(Vector2[] polygon, Vector2 center, double radius)
        {
            int count = polygon.Length;

            for (int i = 0; i < count; i++)
            {
                var p1 = polygon[i];
                var p2 = polygon[(i + 1) % count];

                if (IsLineIntersectCircle(p1, p2, center, radius))
                {
                    return true;
                }
            }

            return IsPointInPolygon(center, polygon);
        }

        public static bool IsLineIntersectCircle(Vector2 p1, Vector2 p2, Vector2 center, double radius)
        {
            double d1 = Vector2.Distance(center, p1);
            double d2 = Vector2.Distance(center, p2);

            if (d1 <= radius && d2 <= radius)
            {
                return false;//包含不是相交
            }
            //直线穿过圆弧一个交点
            if ((d1 <= radius && d2 >= radius) || (d1 >= radius && d2 <= radius))
            {
                return true;
            }

            Vector2 v = p2 - p1;
            Vector2 w = center - p1;

            double dotProduct = Vector2.Dot(w, v);
            double lengthSquared = v.LengthSq();

            if (dotProduct < 0 || dotProduct > lengthSquared)
            {
                return false;
            }

            double distanceToLineSquared = w.LengthSq() - dotProduct * dotProduct / lengthSquared;

            return distanceToLineSquared <= radius * radius;
        }

        public static bool IsPolygonIntersectLine(Vector2[] polygon, Vector2 start, Vector2 end)
        {
            int count = polygon.Length;
            if (polygon.Last().Equals(polygon.First()))
            {
                count -= 1;
            }

            for (int i = 0; i < count; i++)
            {
                var p1 = polygon[i];
                var p2 = polygon[(i + 1) % count];

                if (IsLineIntersectLine(p1, p2, start, end))
                {
                    return true;
                }
            }

            return false;
        }

        public static bool IsPolygonIntersectArc(Vector2[] polygon, Arc2d arc)
        {
            int count = polygon.Length;

            for (int i = 0; i < count; i++)
            {
                var p1 = polygon[i];
                var p2 = polygon[(i + 1) % count];

                if (IsLineIntersectArc(p1, p2, arc))
                {
                    return true;
                }
            }

            return false;
        }

        public static bool IsPolygonContainsLine(Vector2[] polygon, Vector2 start, Vector2 end)
        {
            int count = polygon.Length;
            if (polygon.Last().Equals(polygon.First()))
            {
                count -= 1;
            }
            for (int i = 0; i < count; i++)
            {
                var p1 = polygon[i];
                var p2 = polygon[(i + 1) % count];
                //任何一条边和线段相交，则为不包含
                if (IsLineIntersectLine(p1, p2, start, end))
                {
                    return false;
                }
            }
            //任意一点在多边形内，即为包含，反之为不包含
            return IsPointInPolygon(start, polygon);
        }

        public static bool IsPolygonContainsPolygon(Vector2[] polygon1, Vector2[] polygon2)
        {
            int count = polygon1.Length;
            if (polygon1.Last().Equals(polygon1.First()))
            {
                count -= 1;
            }

            for (int i = 0; i < count; i++)
            {
                var p1 = polygon1[i];
                var p2 = polygon1[(i + 1) % count];
                //任何一条边和多边形相交或者不在多边形内，则为不包含
                if (!IsPolygonContainsLine(polygon2, p1, p2))
                {
                    return false;
                }
            }


            return true;
        }

        public static bool IsLineIntersectLine(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
        {
            double denominator = ((p4.Y - p3.Y) * (p2.X - p1.X)) - ((p4.X - p3.X) * (p2.Y - p1.Y));
            double numerator1 = ((p4.X - p3.X) * (p1.Y - p3.Y)) - ((p4.Y - p3.Y) * (p1.X - p3.X));
            double numerator2 = ((p2.X - p1.X) * (p1.Y - p3.Y)) - ((p2.Y - p1.Y) * (p1.X - p3.X));

            if (denominator == 0)
            {
                if (numerator1 == 0 && numerator2 == 0)
                {
                    // 线段共线
                    return IsPointOnLine(p1, p2, p3) || IsPointOnLine(p1, p2, p4);
                }

                // 线段平行不相交
                return false;
            }

            double r = numerator1 / denominator;
            double s = numerator2 / denominator;

            return r >= 0 && r <= 1 && s >= 0 && s <= 1;
        }

        public static bool IsPointOnLine(Vector2 start, Vector2 end, Vector2 point)
        {
            double minX = Math.Min(start.X, end.X);
            double maxX = Math.Max(start.X, end.X);
            double minY = Math.Min(start.Y, end.Y);
            double maxY = Math.Max(start.Y, end.Y);

            return point.X >= minX && point.X <= maxX && point.Y >= minY && point.Y <= maxY;
        }
        public static int IsTopInLine(Vector2 line1start, Vector2 line1End, Vector2 point)
        {
            Vector2 S;
            Vector2 E;
            S = line1End;
            E = line1start;
            double Tmp = (S.Y - E.Y) * point.X + (E.X - S.X) * point.Y + S.X * E.Y - E.X * S.Y;
            if (Tmp == 0)//线上
            {
                return 0;
            }
            if (Tmp > 0)//右侧
            {
                return 1;
            }
            else//左侧
            { return -1; }
        }
        /// <summary>
        /// 判断点在直线上，但是不在延长线上
        /// </summary>
        /// <param name="line1start"></param>
        /// <param name="line1End"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        public static bool IsPointOnLineExtension(Vector2 line1start, Vector2 line1End, Vector2 point)
        {
            //if(IsTopInLine(line1start, line1End, point) == 0)
            //{
            if (line1start.X > line1End.X && line1start.Y > line1End.Y)
            {
                if ((point.X > line1End.X && point.X < line1start.X) && (point.Y > line1End.Y && point.Y < line1start.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (line1start.X < line1End.X && line1start.Y > line1End.Y)
            {
                if ((point.X < line1End.X && point.X > line1start.X) && (point.Y > line1End.Y && point.Y < line1start.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }
            else if (line1start.X > line1End.X && line1start.Y < line1End.Y)
            {
                if ((point.X > line1End.X && point.X < line1start.X) && (point.Y < line1End.Y && point.Y > line1start.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if ((point.X < line1End.X && point.X > line1start.X) && (point.Y < line1End.Y && point.Y > line1start.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            //}
        }

        /// <summary>
        /// 判断点在圆弧上，但是不在圆弧延长线上
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        public static bool IsPointOnArcExtension(Arc2d arc, Vector2 point)
        {
            if (arc.Startp.X > arc.Endp.X && arc.Startp.Y > arc.Endp.Y)
            {
                if ((point.X > arc.Endp.X && point.X < arc.Startp.X) && (point.Y > arc.Endp.Y && point.Y < arc.Startp.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (arc.Startp.X < arc.Endp.X && arc.Startp.Y > arc.Endp.Y)
            {
                if ((point.X < arc.Endp.X && point.X > arc.Startp.X) && (point.Y > arc.Endp.Y && point.Y < arc.Startp.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }
            else if (arc.Startp.X > arc.Endp.X && arc.Startp.Y < arc.Endp.Y)
            {
                if ((point.X > arc.Endp.X && point.X < arc.Startp.X) && (point.Y < arc.Endp.Y && point.Y > arc.Startp.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if ((point.X < arc.Endp.X && point.X > arc.Startp.X) && (point.Y < arc.Endp.Y && point.Y > arc.Startp.Y))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 三点获得圆心
        /// </summary>
        /// <param name="startp"></param>
        /// <param name="midp"></param>
        /// <param name="endp"></param>
        /// <returns></returns>
        public static Vector2 GetCenter(Vector2 startp, Vector2 midp, Vector2 endp)
        {
            Vector2 Center = new Vector2();
            double a = startp.X - midp.X;
            double b = startp.Y - midp.Y;
            double c = startp.X - endp.X;
            double d = startp.Y - endp.Y;
            double e = ((startp.X * startp.X - midp.X * midp.X) - (midp.Y * midp.Y - startp.Y * startp.Y)) / 2;
            double f = ((startp.X * startp.X - endp.X * endp.X) - (endp.Y * endp.Y - startp.Y * startp.Y)) / 2;

            // 圆心位置 
            var x = (e * d - b * f) / (a * d - b * c);
            var y = (a * f - e * c) / (a * d - b * c);
            Center.X = x;
            Center.Y = y;
            return Center;
        }
        // 判断一个线段是否和圆弧相交
        public static bool IsLineIntersectArc(Vector2 p1, Vector2 p2, Arc2d arc)
        {
            // 确保 p1.x <= p2.x
            if (p1.X > p2.X)
            {
                var temp = p1.Clone();
                p1 = p2;
                p2 = temp;
            }
            // 简化圆弧的相关变量表示
            double a = arc.Center.X;
            double b = arc.Center.Y;
            double r = arc.Radius;
            double theta1 = arc.StartAngle;
            double theta2 = arc.EndAngle;
            // 第一步（粗略判断）：将线段当成直线，将圆弧当成圆，如果直线和圆不相交，则线段和圆弧必然不相交，否则进行下一步判断
            // 1.1 根据公式，计算直线方程 y=kx+c 中的 k 和 c
            double k = (p1.Y - p2.Y) / (p1.X - p2.X);
            double c = p1.Y - (p1.Y - p2.Y) / (p1.X - p2.X) * p1.X;
            // 1.2 根据韦达定理判断式（6）是否存在实数根
            double d = c - b;
            double varDelta = Math.Pow(2 * k * d - 2 * a, 2) - 4 * (1 + k * k) * (a * a + d * d - r * r);
            if (varDelta >= 0)
            {
                // 第二步：判断直线和圆的两个交点是否在线段上，如果不在，说明线段和圆弧必然不相交，否则进行下一步判断
                // 2.1 计算两个交点的坐标(x1,y1)和(x2,y2)
                double x1 = (2 * a - 2 * k * d + Math.Sqrt(varDelta)) / (2 * (1 + k * k));
                double x2 = (2 * a - 2 * k * d - Math.Sqrt(varDelta)) / (2 * (1 + k * k));
                double y1 = k * x1 + c;
                double y2 = k * x2 + c;
                // 2.2 判断两个交点是否相等
                if (varDelta == 0)
                {
                    // 两个交点相等，只需要判断一个就好
                    return IsLineIntersectArcAuxiliaryFunction(p1, p2, a, b, theta1, theta2, x1, y1);
                }
                else
                {
                    // 两个交点不相等，分别进行判断，只要其中一个是线段和圆弧的交点就返回 true
                    return IsLineIntersectArcAuxiliaryFunction(p1, p2, a, b, theta1, theta2, x1, y1) || IsLineIntersectArcAuxiliaryFunction(p1, p2, a, b, theta1, theta2, x2, y2);
                }
            }
            return false;
        }
        /// <summary>
        /// 获得两条线的夹角
        /// </summary>
        /// <param name="line1start"></param>
        /// <param name="line1End"></param>
        /// <param name="line2start"></param>
        /// <param name="line2End"></param>
        /// <returns></returns>
        public static double GetDegreesByTwoLine(Vector2 line1start, Vector2 line1End, Vector2 line2start, Vector2 line2End)
        {
            double x1 = line1start.X;
            double y1 = line1start.Y;
            double x2 = line1End.X;
            double y2 = line1End.Y;
            double x3 = line2start.X;
            double y3 = line2start.Y;
            double x4 = line2End.X;
            double y4 = line2End.Y;
            // 计算线段的向量表示
            double v1x = x2 - x1;
            double v1y = y2 - y1;
            double v2x = x4 - x3;
            double v2y = y4 - y3;
            // 计算向量的内积
            double dotProduct = v1x * v2x + v1y * v2y;
            // 计算向量的长度
            double magnitudeV1 = Math.Sqrt(v1x * v1x + v1y * v1y);
            double magnitudeV2 = Math.Sqrt(v2x * v2x + v2y * v2y);
            // 计算夹角余弦值
            double cosine = dotProduct / (magnitudeV1 * magnitudeV2);
            // 将夹角余弦值转换为角度
            double angleRadians = Math.Acos(cosine);
            double angleDegrees = angleRadians * 180 / Math.PI;
            return angleDegrees;
        }

        // lineIsIntersectArc 的辅助函数：接着第二步判断
        private static bool IsLineIntersectArcAuxiliaryFunction(Vector2 p1, Vector2 p2, double a, double b, double theta1, double theta2, double x1, double y1)
        {
            var eps = 0.0000001;
            // 2.3 判断交点是否在线段上
            if (p1.X <= x1 && x1 <= p2.X)
            {
                // 第三步：交点(x1,y1)在线段上，再判断该点是否在圆弧上，如果在，则说明线段和圆弧相交，且交点为(x1,y1)
                // 3,1 计算 theta ，并转化为角度值
                double theta = Math.Atan((y1 - b) / (x1 - a)) / Math.PI * 180.0;
                // 3.2 修正角度值，确保 theta1 <= theta2
                if (theta1 > theta2)
                {
                    if (theta2 >= 0)
                    {
                        theta1 -= 360;
                    }
                    else
                    {
                        theta2 += 360;
                    }
                }
                if (theta1 < 0 && theta2 < 0)
                {
                    theta1 += 360;
                    theta2 += 360;
                }
                // 3.3 修正 tan 的角度
                if (x1 < a)
                {
                    theta += 180;
                }
                // 3.4 在端点时，由于精度误差，有时可能会出现判断出错 (即出现 10.000000001 > 10 的情况)，故以极小的误差接受(x1,y1)为圆弧的某个端点
                if (Math.Abs(theta1 - theta) < eps || Math.Abs(theta2 - theta) < eps)
                {
                    return true;
                }
                // 3.5 判断 theta 是否在圆弧范围内，如果在则(x1,y1)是线段和圆弧的交点，否则不是
                return theta1 <= theta && theta <= theta2;
            }
            return false;
        }

        public static double PointToLineDistance(Vector2 p1, Vector2 p2, Vector2 p, out Vector2 prjPoint, out double dirDistance)
        {
            var direction = (p2 - p1).Normalize();
            dirDistance = Vector2.Dot((p - p1), direction);
            prjPoint = p1 + direction * dirDistance;
            return Vector2.Distance(prjPoint, p);
        }
        public static int AngleAccuracy = 4;
        public static bool AlmostEqual(double d1, double d2)
        {
            return AlmostEqual(d1, d2, AngleAccuracy);
        }
        public static bool AlmostEqual(double d1, double d2, int accuracy)
        {
            return Math.Round(d1, accuracy) == Math.Round(d2, accuracy);
        }
    }


}